package org.hackystat.app.projectstatus.data;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.hackystat.core.common.project.Project;
import org.hackystat.core.common.project.cache.DailyProjectData;
import org.hackystat.core.common.project.cache.DailyProjectDataCache;
import org.hackystat.core.common.project.cache.DailyProjectDataManager;
import org.hackystat.core.kernel.user.User;
import org.hackystat.core.kernel.util.Day;

/**
 * Used to populate the emails of the ProjectStatus alert with the daily project
 * details data. Processes the dailyProjectDetail data.
 * 
 * @author Josh
 * 
 */
public class ProjectStatusDataManager {

	/** The default project manager. */
	private static ProjectStatusDataManager manager;

	/**
	 * Private constructor.
	 * 
	 */
	private ProjectStatusDataManager() {
	}

	/**
	 * Returns a ProjectStatusDataManager singleton instance.
	 * 
	 * @return Returns the new ProjectStatusDataManager instance.
	 */
	public static ProjectStatusDataManager getInstance() {
		if (manager == null) {
			ProjectStatusDataManager newManager = new ProjectStatusDataManager();
			return newManager;
		} else {
			return manager;
		}
	}

	/**
	 * Attemtpts to retrieve the passed project's raw dailyProjectData
	 * drilldowns.
	 * 
	 * @param user
	 *            The user logged in.
	 * @param project
	 *            The selected project.
	 * @param day
	 *            The day in question.
	 * @return List<List<String[]>> The drillDowns from the project's
	 *         dailyProjectData.
	 */
	public List<List<String[]>> getDailyProjectData(User user,
			Project project, Day day) {

		// Make sure that this day is within the Project's defined interval.
		if (!project.inProjectInterval(day)) {
			System.out.println(day + " is not in project interval: "
					+ project.getInterval());
			return null;
		}

		Collection dailyProjectClasses = DailyProjectDataManager
				.getInstance().getClasses();
		List<List<String[]>> drilldownList = new ArrayList<List<String[]>>();

		for (Iterator j = dailyProjectClasses.iterator(); j.hasNext();) {
			Class dataClass = (Class) j.next();
			DailyProjectData data = DailyProjectDataCache
					.getInstance().get(project, day, dataClass);
			drilldownList.addAll(data.getDrillDowns(user));
		}

		return drilldownList;
	}

	/**
	 * This method is responsible for the parsing of the dailyProjectData and
	 * according to the number of drilldowns collected it constructs the HTML
	 * template inserting the number of drilldown templates required and
	 * according to the amount of data found within those drilldowns it
	 * constructs the number of entries for each specific data class.
	 * 
	 * @param user
	 *            The user requesting the HTML Page.
	 * @param project
	 *            The project associated with this data.
	 * @param day
	 *            The day associated with the data.
	 * @return The template with the data inserted.
	 */
	public String getHTMLPage(User user, Project project, Day day) {
		char quote = '"';

		List<List<String[]>> classDrilldowns = new ArrayList<List<String[]>>();

		String htmlFileString = new String("<html><head>\n"
				+ "<link rel=" + quote + "StyleSheet" + quote
				+ " href=" + quote
				+ "http://www2.hawaii.edu/~jstupple/stylesheet.css"
				+ quote + " type=" + quote + "text/css" + quote
				+ ">\n" + "<link rel=" + quote + "shortcut icon"
				+ quote + " href=" + quote
				+ "http://localhost:8080/hackystat/favicon.ico"
				+ quote
				+ "><title>Hackystat - Daily Project Details</title>"
				+ "</head><body><table>\n" + "  <tbody><tr>\n"
				+ "    <td align=" + quote + "left" + quote
				+ " width=" + quote + "35%" + quote + "><img src="
				+ quote
				+ "http://www2.hawaii.edu/~jstupple/hackystat.gif"
				+ quote + "></td>\n" + "    <td align=" + quote
				+ "center" + quote + " width=" + quote + "30%"
				+ quote + "> <b>Hackystat</b> </td>\n"
				+ "    <td align=" + quote + "right" + quote
				+ " width=" + quote + "35%" + quote
				+ "> <h1>Daily Project Details</h1> </td>\n"
				+ "  </tr>\n" + "</tbody></table>\n" + "<p><img src="
				+ quote
				+ "http://www2.hawaii.edu/~jstupple/spacer.gif"
				+ quote + "></p>\n" + "<p>&nbsp; </p>\n"
				+ "      @drilldowns\n" + "</p>\n" + "</body>\n"
				+ "</html>");

		String newDescriptionTemplate = "";
		String newTitleTemplate = "";
		String newDataTemplate = "";
		String finalDrilldownTemplate = "";
		int a = 0;
		int b = 0;

		String tableStartTag = "<table class=" + quote + "data"
				+ quote + ">\n" + "<tbody>\n";

		String tableEndTag = "</tr>\n</tbody></table>\n<p class="
				+ quote + "medskip" + quote + ">";

		String originalDescriptionTemplate = new String("<tr>\n"
				+ "            <th class=" + quote + "data" + quote
				+ " colspan=" + quote + "10" + quote + " align="
				+ quote + "left" + quote + ">@description</th>\n");

		String originalTitleTemplate = new String("      </tr>\n"
				+ "      <tr>\n" + "                <th class="
				+ quote + "data33" + quote + " align=" + quote
				+ "left" + quote + ">@title</th>\n");

		String originalDataTemplate = new String(
				"                <td class=" + quote + "data" + quote
						+ " align=" + quote + "left" + quote
						+ ">@data</td>\n");

		// This line gathers the actual drilldown data from the classes.
		// It returns immediately if there is no data for this day,
		// and the resulting jsp page should show this error.
		classDrilldowns = getDailyProjectData(user, project, day);

		if (classDrilldowns == null) {
			htmlFileString = htmlFileString.replaceAll("@drilldowns",
					"No daily project data is defined for this day");
			return htmlFileString;
		}
		if (classDrilldowns.isEmpty()) {
			htmlFileString = htmlFileString.replaceAll("@drilldowns",
					"No daily project data is defined for this day");
			return htmlFileString;
		}

		// Attatches the number of data templates that we need.
		for (List<String[]> drilldowns : classDrilldowns) {
			a = 0;
			finalDrilldownTemplate = finalDrilldownTemplate
					.concat(tableStartTag);
			for (String[] sArray : drilldowns) {
				b = 0;
				for (String s : sArray) {
					if (a == 0) {
						newDescriptionTemplate = originalDescriptionTemplate
								.replaceAll("@description", s);
						finalDrilldownTemplate = finalDrilldownTemplate
								.concat(newDescriptionTemplate);
					} else if (a != 0) {
						if (b == 0) {
							newTitleTemplate = originalTitleTemplate
									.replaceAll("@title", s);
							finalDrilldownTemplate = 
								finalDrilldownTemplate
									.concat(newTitleTemplate);
						} else if (b != 0) {
							newDataTemplate = originalDataTemplate
									.replaceAll("@data", s);
							finalDrilldownTemplate = 
								finalDrilldownTemplate
									.concat(newDataTemplate);
						}
					}
					b++;
				}
				a++;
			}
			finalDrilldownTemplate = finalDrilldownTemplate
					.concat(tableEndTag);
		}

		htmlFileString = htmlFileString.replaceAll("@drilldowns",
				finalDrilldownTemplate);

		return htmlFileString;

	}

	/**
	 * Implements gathering of the fileInput which takes a BufferedReader as a
	 * parameter, but in the future should provide gathering of input data from
	 * dynamically generated HTML pages.
	 * 
	 * @param br
	 *            BufferedReader input file.
	 * @return String A String containing the HTML/text.
	 */
	public static List<String> getFileStringList(BufferedReader br) {
		List<String> fileData = new ArrayList<String>();
		String fileString = "";
		try {
			while ((fileString = br.readLine()) != null) {
				fileData.add(fileString);
			}
		} catch (IOException e) {
			System.out.println("IOException");
		}
		return fileData;
	}

	/**
	 * Converts a list to a string. For testing purposes.
	 * 
	 * @param list
	 *            The list to be converted.
	 * @return The former list now as a concatinated String.
	 */
	public String listToString(List<String> list) {
		String listString = "";

		for (String s : list) {
			if (s.length() == 0) {
				return "";
			} else {
				listString = listString.concat(s).concat("\n");
			}
		}

		return listString;
	}

}
